<?php
/**
 * Each engineer has a duty to keep the code elegant
 * Created by wolffy.
 * Author @wolffy<13750088090@sina.cn>
 * Date: 2018/8/19
 * Time: 19:30
 */
namespace App\Services;

use App\Repositories\RepaymentAccountWithdrawRepository;
use App\Repositories\RepaymentBillRepository;
use App\Repositories\RepaymentPlanConsumeRepository;
use App\Repositories\RepaymentPlanFailHandlersRepository;
use App\Repositories\RepaymentPlanRepaymentRepository;
use App\Repositories\RepaymentPlanRepository;
use App\Repositories\ThreeApiErrorLogsRepository;
use App\Repositories\UserCreditCardRepository;
use App\Repositories\UserRepository;
use App\Services\RepaymentPay\LandingPayCService;
use App\Services\RepaymentPay\LargePayXService;
use Illuminate\Support\Facades\Log;

class RepaymentPlanJobsService extends CommonService
{
    protected $userRepository;
    protected $userCreditCardRepository;
    protected $repaymentBillRepository;
    protected $repaymentPlanRepository;
    protected $repaymentPlanConsumeRepository;
    protected $repaymentPlanRepaymentRepository;
    protected $threeApiErrorLogsRepository;
    protected $repaymentPlanFailHandlersRepository;
    protected $cloudspSMS;
    protected $messageService;
    protected $repaymentAccountWithdrawRepository;
    protected $landingPayCService;
    protected $largePayXService;

    public function __construct(UserRepository $userRepository,
                                UserCreditCardRepository $userCreditCardRepository,
                                RepaymentBillRepository $repaymentBillRepository,
                                RepaymentPlanRepository $repaymentPlanRepository,
                                RepaymentPlanConsumeRepository $repaymentPlanConsumeRepository,
                                RepaymentPlanRepaymentRepository $repaymentPlanRepaymentRepository,
                                ThreeApiErrorLogsRepository $threeApiErrorLogsRepository,
                                RepaymentPlanFailHandlersRepository $repaymentPlanFailHandlersRepository,
                                CloudspSMS $cloudspSMS, MessageService $messageService,
                                RepaymentAccountWithdrawRepository $repaymentAccountWithdrawRepository,
                                LandingPayCService $landingPayCService,
                                LargePayXService $largePayXService)
    {
        $this->userRepository = $userRepository;
        $this->userCreditCardRepository = $userCreditCardRepository;
        $this->repaymentBillRepository = $repaymentBillRepository;
        $this->repaymentPlanRepository = $repaymentPlanRepository;
        $this->repaymentPlanConsumeRepository = $repaymentPlanConsumeRepository;
        $this->repaymentPlanRepaymentRepository = $repaymentPlanRepaymentRepository;
        $this->threeApiErrorLogsRepository = $threeApiErrorLogsRepository;
        $this->repaymentPlanFailHandlersRepository = $repaymentPlanFailHandlersRepository;
        $this->cloudspSMS = $cloudspSMS;
        $this->messageService = $messageService;
        $this->repaymentAccountWithdrawRepository = $repaymentAccountWithdrawRepository;
        $this->landingPayCService = $landingPayCService;
        $this->largePayXService = $largePayXService;
    }

    protected function redisListArraySort($data, $keySort)
    {
        $res = [];
        foreach ($data as $key=>$value) {
            $res[$key] = json_decode($value, true);
        }
        $res = arraySort($res, $keySort, 'asc');
        $redisSort = array_values($res);
        return json_encode($redisSort[0]);
    }


    /**
     * 进消费任务与还款任务
     *  [
     * "id" => 70
     * "plan_consume_sn" => "A826812391527542"
     * "repayment_plan_id" => 13
     * "plan_repayment_id" => 24
     * "consume_money" => "44.21"
     * "consume_date" => "2018-08-26"
     * "consume_time" => 1535250240
     * "consume_type_mcc" => "5948"
     * "consume_type_name" => "箱包皮具"
     * "consume_service_charge" => "1.28"
     * "repayment_consume_status" => 2000
     * "create_plan_consume_time" => 1535281239
     * ]
     */
    public function consumeJobs()
    {
        Log::alert('consumeJobs');
        if (time() < strtotime('7:30') || time() > strtotime('22:00')) {
            die('不在执行时间内');
        }
        //执行日期 每天
        $nowDate = date('Y-m-d');
        $planConsumeRedisKey = $this->repaymentPlanConsume() . $nowDate . ':' . $nowDate;
        $getPlanConsume = $this->redis()->lRange($planConsumeRedisKey, 0, -1);
        if (!empty($getPlanConsume)) {
            $value = $this->redisListArraySort($getPlanConsume, 'consume_time');
            $consume = json_decode($value, true);
            $repaymentPlan = $this->repaymentPlanRepository->byId($consume['repayment_plan_id']);
            if (1003 == $repaymentPlan->repayment_plan_status || 1004 == $repaymentPlan->repayment_plan_status) {
                Log::info('1003=1004==' . json_encode($value));
                $this->redis()->lRem($planConsumeRedisKey, 0, $value);
            }
            $consumeLockTimeRedisKey = $this->consumeLockTimeRedisKey();
            $consumeLockTime = $this->redis()->get($consumeLockTimeRedisKey);
            if ($consumeLockTime > 0) {
                $timeA = $consumeLockTime;
                $timeB = 0;
            } else {
                $timeA = time();
                $timeB = time();
            }
            //是否到达执行消费的时间，则调用消费接口
            if ($timeA >= $consume['consume_time'] && $timeB <= $consume['consume_time'] + 59) {
//            if ($consume['consume_time'] <= 1548414024) {
                //计划一开始状态为待执行 则更新为执行中
                if (1000 == $repaymentPlan->repayment_plan_status) {
                    $repaymentPlan->update(['repayment_plan_status' => 1001, 'update_plan_time' => time()]);
                }
                //上一笔消费失败，计划处于继续执行状态，当他是继续执行状态，说明已经进入到下一次消费，直接更新为失败
                if (1005 == $repaymentPlan->repayment_plan_status) {
                    //先删除redis数据，防止重复执行
                    $this->redis()->lRem($planConsumeRedisKey, 0, $value);
                    $repaymentPlan->update(['repayment_plan_status' => 1003, 'update_plan_time' => time()]);
                    //失败提现
                    $this->intoRepaymentAutoWithdrawJobs($consume['consume_passage_id'], $repaymentPlan->user_id,
                        $consume['repayment_plan_id'], $consume['plan_repayment_id']);
                }
                if (1001 == $repaymentPlan->repayment_plan_status) {
                    $lockKey = $planConsumeRedisKey . '_LOCK';
                    $isLock = $this->redis()->setnx($lockKey, 1); //加锁
                    //获取锁权限
                    if ($isLock) {
                        //先删除redis数据，防止重复执行
                        $this->redis()->lRem($planConsumeRedisKey, 0, $value);
                        Log::info('100=100==' . json_encode($value));
                        //区分大小额
                        $res = false;
                        if (isset($consume['consume_passage_id'])) {
                            if (1 == $consume['consume_passage_id']) {
                                $res = $this->consumeSmallAmount($repaymentPlan, $consume);
                            }
                            if (3 == $consume['consume_passage_id']) {
                                $res = $this->consumeLargeAmount($repaymentPlan, $consume);
                            }
                        } else {
                            $res = $this->consumeSmallAmount($repaymentPlan, $consume);
                        }
                        if ($res) {
                            //释放锁
                            $this->redis()->del($lockKey);
                        }
                    } else {
                        //防止死锁
                        if($this->redis()->ttl($lockKey) == -1) {
                            $this->redis()->expire($lockKey, 10);
                        }
                    }
                }
            }
        }
    }

    /**
     * 小额c消费
     * @param $repaymentPlan
     * @param $consume
     */
    public function consumeSmallAmount($repaymentPlan, $consume)
    {
        $address = json_encode(unserialize($consume['consume_address']));
        $userId = $repaymentPlan->user_id;
        $creditCard = $this->userCreditCardRepository->isExistUserBankNo($userId, $consume['bank_no']);
        $result = $this->landingPayCService->trade($consume['plan_consume_sn'], $consume['sub_merchant_no'], $creditCard->bank_code,
            $consume['bank_no'], $creditCard->bank_mobile, $creditCard->expire_date, $creditCard->cvn2,
            $consume['consume_money'], $consume['consume_rate'], $consume['consume_every_time_price'], $address);
        Log::info('小额消费c' . json_encode($result));
        $errorData = [
            'order_no' => $consume['plan_consume_sn'],
            'error_code' => $result['response']['code'],
            'error_msg' => json_encode($result),
            'api_type' => 4
        ];
        $userId = $repaymentPlan->user_id;
        if ($result['response']['code'] == 0) {
            //更新消费状态为执行中
            $this->repaymentPlanConsumeRepository->updateStatusById($consume['id'], 2001, '');
            $this->threeApiErrorLogsRepository->create($errorData);
        } else {
            //更新消费状态为失败
            $this->updateConsumeFail($userId, $repaymentPlan, $consume, $errorData, $result['response']['message']);
        }
        return true;
    }

    /**
     * 大额e消费
     * @param $repaymentPlan
     * @param $consume
     */
    public function consumeLargeAmount($repaymentPlan, $consume)
    {
        $address = json_encode(unserialize($consume['consume_address']));
        $userId = $repaymentPlan->user_id;
        $creditCard = $this->userCreditCardRepository->isExistUserBankNo($userId, $consume['bank_no']);
        $result = $this->largePayXService->trade($consume['plan_consume_sn'], $consume['sub_merchant_no'], $creditCard->bank_code,
            $consume['bank_no'], $creditCard->bank_mobile, $creditCard->expire_date, $creditCard->cvn2,
            $consume['consume_money'], $consume['consume_rate'], $consume['consume_every_time_price'], $address);
        Log::info('大额消费c' . json_encode($result));
        $errorData = [
            'order_no' => $consume['plan_consume_sn'],
            'error_code' => $result['response']['code'],
            'error_msg' => json_encode($result),
            'api_type' => 17
        ];
        $userId = $repaymentPlan->user_id;
        if ($result['response']['code'] == 0) {
            //更新消费状态为执行中
            $this->repaymentPlanConsumeRepository->updateStatusById($consume['id'], 2001, '');
            $this->threeApiErrorLogsRepository->create($errorData);
        } else {
            //更新消费状态为失败
            $this->updateConsumeFail($userId, $repaymentPlan, $consume, $errorData, $result['response']['message']);
        }
        return true;
    }

    /**
     * 更新消费失败
     * @param $userId
     * @param $repaymentPlan
     * @param $consume
     * @param $errorData
     * @param $failMessage
     */
    protected function updateConsumeFail($userId, $repaymentPlan, $consume, $errorData, $failMessage)
    {
        //更新消费状态为失败
        $this->repaymentPlanConsumeRepository->updateStatusById($consume['id'], 2003, $failMessage);
        //更新计划为继续执行
        $repaymentPlan->update(['repayment_plan_status' => 1005, 'update_plan_time' => time()]);
        $this->threeApiErrorLogsRepository->create($errorData);
        //您的尾号{1}订单{2}执行失败！请重新制定计划。回T退订
        $content = substr($consume['bank_no'], -4) . '##' . $consume['plan_consume_sn'];
        $user = $this->userRepository->byId($userId);
        $this->cloudspSMS->sendSMSNotify($user->mobile, $content, 'failOrder', 8);
        //发送消费失败消息提醒
        $creditCard = $this->userCreditCardRepository->isExistUserBankNo($userId, $consume['bank_no']);
        $this->messageService->messageTemplate(16, $user->invited_code, $consume['bank_no'], $creditCard->bank_description,
            $consume['consume_money'], '', '', $consume['repayment_plan_id'], '', '');
    }

    /**
     * 还款任务
     * [
     * "id" => 34
     * "plan_repayment_sn" => "A826858018728385"
     * "repayment_plan_id" => 18
     * "repayment_every_time_date" => "2018-08-26"
     * "repayment_every_time" => 1535271720
     * "repayment_every_time_money" => "104.00"
     * "repayment_every_status" => 3000
     * "create_plan_repayment_time" => 1535285801
     * "sub_merchant_no" => "68706638"
     * "bank_no" => "6258081666513607"
     * ]
     */
    public function repaymentJobs()
    {
        Log::alert('repaymentJobs');
        if (time() < strtotime('7:30') || time() > strtotime('22:00')) {
            die('不在执行时间内');
        }
        //执行日期 每天
        $nowDate = date('Y-m-d');
        $repaymentPlanRedisKey = $this->repaymentPlanRepayment() . $nowDate . ':' . $nowDate;
        $getPlanRepayment = $this->redis()->lRange($repaymentPlanRedisKey, 0, -1);
        if (!empty($getPlanRepayment)) {
            $value = $this->redisListArraySort($getPlanRepayment, 'repayment_every_time');
            $repayment = json_decode($value, true);
            $repaymentPlan = $this->repaymentPlanRepository->byId($repayment['repayment_plan_id']);
            if (1003 == $repaymentPlan->repayment_plan_status || 1004 == $repaymentPlan->repayment_plan_status) {
                $this->redis()->lRem($repaymentPlanRedisKey, 0, $value);
                Log::info('1003=1004==' . json_encode($value));
            }
            $repaymentLockTimeRedisKey = $this->repaymentLockTimeRedisKey();
            $repaymentLockTime = $this->redis()->get($repaymentLockTimeRedisKey);
            if ($repaymentLockTime > 0) {
                $timeA = $repaymentLockTime;
                $timeB = 0;
            } else {
                $timeA = time();
                $timeB = time();
            }
            //是否到达执行还款的时间，则调用还款接口
            if ($timeA >= $repayment['repayment_every_time'] && $timeB <= $repayment['repayment_every_time'] + 59) {
//            if ($repayment['repayment_every_time'] <= 1548579632) {
                if (1005 == $repaymentPlan->repayment_plan_status) {
                    //先删除redis数据，防止重复执行
                    $this->redis()->lRem($repaymentPlanRedisKey, 0, $value);
                    $repaymentPlan->update(['repayment_plan_status' => 1003, 'update_plan_time' => time()]);
                    //失败提现
                    $this->intoRepaymentAutoWithdrawJobs($repayment['repayment_passage_id'], $repaymentPlan->user_id,
                        $repayment['repayment_plan_id'], $repayment['id']);
                }
                if (1001 == $repaymentPlan->repayment_plan_status) {
                    $lockKey = $repaymentPlanRedisKey . '_LOCK';
                    $isLock = $this->redis()->setnx($lockKey, 1); //加锁
                    //获取锁权限
                    if ($isLock) {
                        //先删除redis数据，防止重复执行
                        $this->redis()->lRem($repaymentPlanRedisKey, 0, $value);
                        Log::info('1001===' . json_encode($value));
                        //区分大小额
                        $res = false;
                        if (isset($repayment['repayment_passage_id'])) {
                            if (1 == $repayment['repayment_passage_id']) {
                                $this->repaymentSmallAmount($repaymentPlan, $repayment);
                            }
                            if (3 == $repayment['repayment_passage_id']) {
                                $this->repaymentLargeAmount($repaymentPlan, $repayment);
                            }
                        } else {
                            $this->repaymentSmallAmount($repaymentPlan, $repayment);
                        }
                        if ($res) {
                            //释放锁
                            $this->redis()->del($lockKey);
                        }
                    } else {
                        //防止死锁
                        if($this->redis()->ttl($lockKey) == -1) {
                            $this->redis()->expire($lockKey, 10);
                        }
                    }
                }
            }
        }
    }

    /**
     * 小额还款
     * @param $repaymentPlan
     * @param $repayment
     */
    public function repaymentSmallAmount($repaymentPlan, $repayment)
    {
        $this->repaymentPlanRepaymentRepository->updateSnById($repayment['id'], $repayment['plan_repayment_sn']);
        $userId = $repaymentPlan->user_id;
        $creditCard = $this->userCreditCardRepository->isExistUserBankNo($userId, $repayment['bank_no']);
        $result = $this->landingPayCService->withdraw($repayment['plan_repayment_sn'], $repayment['sub_merchant_no'], $creditCard->bank_code,
            $creditCard->bank_description, $repayment['bank_no'], $creditCard->bank_mobile, $repayment['repayment_every_time_money'], '0');
        Log::info('小额还款' . json_encode($result));
        $errorData = [
            'order_no' => $repayment['plan_repayment_sn'],
            'error_code' => $result['response']['code'],
            'error_msg' => json_encode($result),
            'api_type' => 6
        ];
        $userId = $repaymentPlan->user_id;
        if ($result['response']['code'] == 0) {
            //更新状态为执行中
            $this->repaymentPlanRepaymentRepository->updateStatusById($repayment['id'], 3001, '');
            $this->threeApiErrorLogsRepository->create($errorData);
        } else {
            //更新还款状态为失败
            $this->updateRepaymentFail($userId, $repaymentPlan, $repayment, $errorData, $result['response']['message']);
        }
        return true;
    }

    /**
     * 大额e还款
     * @param $repaymentPlan
     * @param $repayment
     */
    public function repaymentLargeAmount($repaymentPlan, $repayment)
    {
        $this->repaymentPlanRepaymentRepository->updateSnById($repayment['id'], $repayment['plan_repayment_sn']);
        $userId = $repaymentPlan->user_id;
        $creditCard = $this->userCreditCardRepository->isExistUserBankNo($userId, $repayment['bank_no']);
        $user = $this->userRepository->byId($userId);
        $result = $this->largePayXService->withdraw($repayment['plan_repayment_sn'], $repayment['sub_merchant_no'], $user->idcard_number,
            $creditCard->bank_code, $repayment['bank_no'], $repayment['repayment_every_time_money'], '0', '0');
        Log::info('大额还款' . json_encode($result));
        $errorData = [
            'order_no' => $repayment['plan_repayment_sn'],
            'error_code' => $result['response']['code'],
            'error_msg' => json_encode($result),
            'api_type' => 19
        ];
        $userId = $repaymentPlan->user_id;
        if ($result['response']['code'] == 0) {
            //更新状态为执行中
            $this->repaymentPlanRepaymentRepository->updateStatusById($repayment['id'], 3001, '');
            $this->threeApiErrorLogsRepository->create($errorData);
        } else {
            //更新还款状态为失败
            $this->updateRepaymentFail($userId, $repaymentPlan, $repayment, $errorData, $result['response']['message']);
        }
        return true;
    }

    /**
     * 更新还款失败
     * @param $userId
     * @param $repaymentPlan
     * @param $repayment
     * @param $errorData
     * @param $failMessage
     */
    protected function updateRepaymentFail($userId, $repaymentPlan, $repayment, $errorData, $failMessage)
    {
        //更新还款状态为失败
        $this->repaymentPlanRepaymentRepository->updateStatusById($repayment['id'], 3003, $failMessage);
        //更新计划为失败
        $repaymentPlan->update(['repayment_plan_status' => 1003, 'update_plan_time' => time()]);
        $this->threeApiErrorLogsRepository->create($errorData);
        //失败提现
        $this->intoRepaymentAutoWithdrawJobs($repayment['repayment_passage_id'], $userId, $repayment['repayment_plan_id'], $repayment['id']);
        //发送还款失败消息提醒
        $user = $this->userRepository->byId($userId);
        $creditCard = $this->userCreditCardRepository->isExistUserBankNo($userId, $repayment['bank_no']);
        $this->messageService->messageTemplate(2, $user->invited_code, $repayment['bank_no'], $creditCard->bank_description,
            0, '', '', $repayment['id'], '', '');
        //您的尾号{1}订单{2}执行失败！请重新制定计划。回T退订
        $content = substr($repayment['bank_no'], -4) . '##' . $repayment['plan_repayment_sn'];
        $this->cloudspSMS->sendSMSNotify($user->mobile, $content, 'failOrder', 8);
    }

    /**
     * 进入还款自动提现任务
     * @param $passageId
     * @param $userId
     * @param $repaymentPlanId
     * @param $planRepaymentId
     */
    public function intoRepaymentAutoWithdrawJobs($passageId, $userId, $repaymentPlanId, $planRepaymentId)
    {
        //进入自动提现任务
        $planRepaymentRedisKey = $this->repaymentPlanAutoWithdrawRedisKey();
        $data = [
            'passage_id' => $passageId,
            'user_id' => $userId,
            'repayment_plan_id' => $repaymentPlanId,
            'plan_repayment_id' => $planRepaymentId,
            'create_time' => time(),
        ];
        $this->redis()->rPush($planRepaymentRedisKey, json_encode($data));//尾追加
    }

    /**
     * 小额c提现
     * @param $repaymentPlan
     * @param $repayment
     */
    public function withdrawSmallAmount($passageId, $userId, $orderNo, $userPassageMerchantNo,
                                        $withdrawMoney, $creditCardId, $bankNo, $bankCode, $bankName,
                                        $bankMobile, $repaymentPlanId, $planRepaymentId, $createTime)
    {
        $creditCard = $this->userCreditCardRepository->isExistUserBankNo($userId, $bankNo);
        $result = $this->landingPayCService->withdrawHandle($orderNo, $userPassageMerchantNo, $creditCard->bank_code,
            $creditCard->bank_description, $bankNo, $creditCard->bank_mobile, $withdrawMoney, '0');
        Log::info('小额c自动提现：' . json_encode($result));
        $errorData = [
            'order_no' => $orderNo,
            'error_code' => $result['response']['code'],
            'error_msg' => json_encode($result),
            'api_type' => 6
        ];
        $data = [
            'withdraw_no' => $orderNo,
            'passage_id' => $passageId,
            'repayment_plan_id' => $repaymentPlanId,
            'plan_repayment_id' => $planRepaymentId,
            'user_id' => $userId,
            'credit_card_id' => $creditCardId,
            'bank_no' => $bankNo,
            'bank_code' => $bankCode,
            'bank_description' => $bankName,
            'withdraw_money' => $withdrawMoney,
            'withdraw_service_charge' => 0,
            'create_time' => $createTime,
            'sub_merchant_no' => $userPassageMerchantNo,
        ];
        if ($result['response']['code'] == 0) {
            $data['withdraw_status'] = 4001;
            //清除还款金账户的缓存
            $redisKey = $this->repaymentAccountMoney() . 'passage_id_' . $passageId . '_user_id_' . $userId;
            $this->redis()->del($redisKey);
            $this->threeApiErrorLogsRepository->create($errorData);
        } else {
            $data['withdraw_status'] = 4003;
            $data['fail_message'] = $result['response']['message'];
            Log::info('自动处理进入手动处理');
            //自动处理进入手动处理
            $failData = [
                'fail_repayment_sn' => $orderNo,
                'repayment_plan_id' => $repaymentPlanId,
                'plan_repayment_id' => $planRepaymentId,
                'user_id' => $userId,
                'credit_card_id' => $creditCardId,
                'repayment_passage_id' => $passageId,
                'repayment_money' => $withdrawMoney,
                'sub_merchant_no' => $userPassageMerchantNo,
                'bank_no' => $bankNo,
                'bank_mobile' => $bankMobile,
                'api_result' => json_encode($result),
                'create_time' => time(),
            ];
            $this->repaymentPlanFailHandlersRepository->create($failData);
        }
        $this->repaymentAccountWithdrawRepository->create($data);
        $this->threeApiErrorLogsRepository->create($errorData);
    }

    /**
     * 大额e提现
     * @param $repaymentPlan
     * @param $repayment
     */
    public function withdrawLargeAmount($passageId, $userId, $orderNo, $userPassageMerchantNo,
                                        $withdrawMoney, $creditCardId, $bankNo, $bankCode, $bankName,
                                        $bankMobile, $repaymentPlanId, $planRepaymentId, $createTime)
    {
        $creditCard = $this->userCreditCardRepository->isExistUserBankNo($userId, $bankNo);
        $user = $this->userRepository->byId($userId);
        $result = $this->largePayXService->withdraw($orderNo, $userPassageMerchantNo, $user->idcard_number,
            $creditCard->bank_code, $bankNo, $withdrawMoney, '0', '0');
        Log::info('大额e自动提现：' . json_encode($result));
        $errorData = [
            'order_no' => $orderNo,
            'error_code' => $result['response']['code'],
            'error_msg' => json_encode($result),
            'api_type' => 27
        ];
        $data = [
            'withdraw_no' => $orderNo,
            'passage_id' => $passageId,
            'repayment_plan_id' => $repaymentPlanId,
            'plan_repayment_id' => $planRepaymentId,
            'user_id' => $userId,
            'credit_card_id' => $creditCardId,
            'bank_no' => $bankNo,
            'bank_code' => $bankCode,
            'bank_description' => $bankName,
            'withdraw_money' => $withdrawMoney,
            'withdraw_service_charge' => 0,
            'create_time' => $createTime,
            'sub_merchant_no' => $userPassageMerchantNo,
        ];
        if ($result['response']['code'] == 0) {
            $data['withdraw_status'] = 4001;
            //清除还款金账户的缓存
            $redisKey = $this->repaymentAccountMoney() . 'passage_id_' . $passageId . '_user_id_' . $userId;
            $this->redis()->del($redisKey);
            $this->threeApiErrorLogsRepository->create($errorData);
        } else {
            $data['withdraw_status'] = 4003;
            $data['fail_message'] = $result['response']['message'];
            Log::info('自动处理进入手动处理');
            //自动处理进入手动处理
            $failData = [
                'fail_repayment_sn' => $orderNo,
                'repayment_plan_id' => $repaymentPlanId,
                'plan_repayment_id' => $planRepaymentId,
                'user_id' => $userId,
                'credit_card_id' => $creditCardId,
                'repayment_passage_id' => $passageId,
                'repayment_date' => date('Y-m-d'),
                'repayment_time' => time(),
                'repayment_money' => $withdrawMoney,
                'sub_merchant_no' => $userPassageMerchantNo,
                'bank_no' => $bankNo,
                'bank_mobile' => $bankMobile,
                'api_result' => json_encode($result),
                'create_time' => time(),
            ];
            $this->repaymentPlanFailHandlersRepository->create($failData);
        }
        $this->repaymentAccountWithdrawRepository->create($data);
        $this->threeApiErrorLogsRepository->create($errorData);
    }

    /**
     * 还款计划取消超过交易时间自动提现任务
     */
    public function repaymentPlanAutoWithdrawJobs()
    {
        Log::alert('repaymentPlanAutoWithdrawJobs');
        if (time() > strtotime('7:30') && time() < strtotime('22:00')) {
            $repaymentStopOverTimeAutoWithdrawRedisKey = $this->repaymentPlanAutoWithdrawRedisKey();
            $getData = $this->redis()->lRange($repaymentStopOverTimeAutoWithdrawRedisKey, 0, -1);
            if (!empty($getData)) {
                foreach ($getData as $key=>$value) {
                    //第三方接口单次访问需2s，防止并发，1分钟对账10条
                    if ($key < 10) {
                        $info = json_decode($value, true);
                        if (time() >= $info['create_time'] + 300) {
                            $this->redis()->lRem($repaymentStopOverTimeAutoWithdrawRedisKey, 0, $value);
                            Log::alert('repaymentPlanAutoWithdrawJobs==' . $value);
                            $repaymentWithdrawHowMuch = $this->repaymentWithdrawHowMuch($info['repayment_plan_id']);
                            $repaymentPlan = $this->repaymentPlanRepository->byId($info['repayment_plan_id']);
                            $repaymentPlanServiceCharge = $repaymentPlan->repayment_service_charge;
                            $repaymentWithdrawMoney = $this->repaymentWithdrawMoney($repaymentWithdrawHowMuch['repayment_every_time_money'], $repaymentWithdrawHowMuch['no_consume_money'],
                                $repaymentPlanServiceCharge, $repaymentWithdrawHowMuch['already_consume_service_charge']);
                            if ((int)$repaymentWithdrawMoney <= 0) {
                                continue;
                            }
                            Log::alert('repaymentPlanAutoWithdrawJobs==money' . $repaymentWithdrawMoney);
                            $bill = $this->repaymentBillRepository->byId($repaymentPlan->repayment_bill_id);
                            $creditCard = $this->userCreditCardRepository->validateCreditCardIsUser($bill->credit_card_id, $info['user_id']);
                            $orderNo = makeOrderNo();
                            if ($info['passage_id'] == 1) {
                                $this->withdrawSmallAmount(1, $info['user_id'], $orderNo, $repaymentWithdrawHowMuch['sub_merchant_no'],
                                    $repaymentWithdrawMoney, $creditCard->id, $creditCard->bank_no, $creditCard->bank_code,
                                    $creditCard->bank_description, $creditCard->bank_mobile, $info['repayment_plan_id'], $info['plan_repayment_id'], $info['create_time']);
                            }
                            if ($info['passage_id'] == 3) {
                                $this->withdrawLargeAmount(3, $info['user_id'], $orderNo, $repaymentWithdrawHowMuch['sub_merchant_no'],
                                    $repaymentWithdrawMoney, $creditCard->id, $creditCard->bank_no, $creditCard->bank_code,
                                    $creditCard->bank_description, $creditCard->bank_mobile, $info['repayment_plan_id'], $info['plan_repayment_id'], $info['create_time']);
                            }
                        }
                    }
                }
            }
        }
    }

    /**
     * 自动还款提现计算金额
     * @param $repaymentPlanId
     * @return array
     */
    public function repaymentWithdrawHowMuch($repaymentPlanId)
    {
        $repayment = $this->repaymentPlanRepaymentRepository->planRepaymentToStatus($repaymentPlanId);
        $noConsumeMoney = $this->repaymentPlanConsumeRepository->planRepaymentConsumeMoneySum($repayment->id);
        $alreadyConsumeServiceCharge = $this->repaymentPlanConsumeRepository->byStatusConsumeServiceChargeSum($repaymentPlanId, 2002);
        return [
            'no_consume_money' => $noConsumeMoney,
            'already_consume_service_charge' => $alreadyConsumeServiceCharge,
            'repayment_every_time_money' => $repayment->repayment_every_time_money,
            'sub_merchant_no' => $repayment->sub_merchant_no,
        ];
    }
}
